#include "DmMainAfx.h"

#include "Blend.h"
#include "xGraphic_Init.h"
#include "xGraphic_InternalFun.h"

namespace xRender
{
    BYTE GetBitsPixelType(WORD bitsPixel)
    {
        BYTE ret = BITS_32;
        switch (bitsPixel)
        {
        case 8:
            ret = BITS_8;
            break;
        case 24:
            ret = BITS_24;
            break;
        case 32:
            ret = BITS_32;
            break;
        }
        return ret;
    }

    BOOL IsNeedDrawColor(xARGB x, BLENDFILTER filter)
    {
        if (filter.filter == BLEND_MULTIPLY)
        {
            if (x.argb == 0xFFFFFFFF)
            {
                return FALSE;
            }
        }
        else if (filter.filter == BLEND_ALPHA || filter.filter == BLEND_KEYCOLOR)
        {
            if (x.alpha == 0x00)
            {
                return FALSE;
            }
        }
        else if (filter.filter == BLEND_OR)
        {
            if (x.argb == 0xFFFFFFFF)
            {
                return FALSE;
            }
        }

        return TRUE;
    }

    BOOL InternalDrawColorCPU(PBITMAP lpbDst, xARGB x, BLENDFILTER filter)
    {
        switch (filter.filter)
        {
        case BLEND_SRC:
            {
                return xRender::BlendSrcColor(lpbDst, x);
            }
            break;
        case BLEND_MULTIPLY:
            {
                if (x.argb == 0x00000000)
                {
                    return xRender::BlendSrcColor(lpbDst, x);
                }
                else if (x.argb == 0xFFFFFFFF)
                {
                    return TRUE;
                }
                return xRender::BlendMulColor(lpbDst, x);
            }
            break;
        case BLEND_OR:
            {
                if (x.argb == 0xFFFFFFFF)
                {
                    return TRUE;
                }
                else if (x.argb == 0x00000000)
                {
                    return xRender::BlendSrcColor(lpbDst, x);
                }
                return xRender::BlendOrColor(lpbDst, x);
            }
            break;
        case BLEND_GRAY:
            {
                if (x.alpha == 0)
                {
                    return TRUE;
                }
                return xRender::BlendGrayColor(lpbDst, x);
            }
            break;
        case BLEND_DSTOVER:
            {
                return xRender::BlendDstOverColor(lpbDst, x);
            }
            break;
        default:
            {
                if (x.alpha == 0)
                {
                    return TRUE;
                }
                else if (x.alpha == 0xFF)
                {
                    return xRender::BlendSrcColor(lpbDst, x);
                }
                return xRender::BlendSrcOverColor(lpbDst, x);
            }
        }

        return TRUE;
    }

    BOOL InternalDrawBitmapCPU(PBITMAP lpbDst, PBITMAPEX lpbSrc, BLENDFILTER filter, DWORD dwFlag, BYTE alpha)
    {
        if (!lpbDst || !lpbSrc)
            return FALSE;
        
        BYTE bitsPixel = GetBitsPixelType(lpbSrc->bmBitsPixel);

        if (filter.filter == BLEND_MULTIPLY)
        {
            if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
                xRender::BlendMul[bitsPixel](lpbDst, lpbSrc);
            else
                xRender::BlendMulStretch[bitsPixel](lpbDst, lpbSrc);
        }
		else if (filter.filter == BLEND_DSTOVER)
		{
            if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
                xRender::BlendDstOver[bitsPixel](lpbDst, lpbSrc);
            else
                xRender::BlendDstOverStretch[bitsPixel](lpbDst, lpbSrc);
		}
        else if (filter.filter == BLEND_ALPHA || alpha != 0xFF)
        {
            if (alpha == 0)
            {
                return TRUE;
            }
            else if (alpha == 0xFF)
            {
                if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
                    xRender::BlendSrcOver[bitsPixel](lpbDst, lpbSrc);
                else
                {
                    if (dwFlag == DRAW_NORMAL)
                        xRender::BlendSrcOverStretch[bitsPixel](lpbDst, lpbSrc);
                    else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                        xRender::BlendSrcOverStretchBicubic[bitsPixel](lpbDst, lpbSrc);
                    else
                        xRender::BlendSrcOverStretchBilinear[bitsPixel](lpbDst, lpbSrc);
                }
            }
            else
            {
                if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
                    xRender::BlendAlpha[bitsPixel](lpbDst, lpbSrc, alpha);
                else
                {
                    if (dwFlag == DRAW_NORMAL)
                        xRender::BlendAlphaStretch[bitsPixel](lpbDst, lpbSrc, alpha);
                    else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                        xRender::BlendAlphaStretchBicubic[bitsPixel](lpbDst, lpbSrc, alpha);
                    else
                        xRender::BlendAlphaStretchBilinear[bitsPixel](lpbDst, lpbSrc, alpha);
                }
            }
        }
        else if (filter.filter == BLEND_KEYCOLOR)
        {
            xARGB x;
            if (bitsPixel == BITS_24)
            {
                x = xARGBfrom(0xFF, filter.red, filter.green, filter.blue);
            }
            else
            {
                x = xARGBfrom(0x00, filter.red, filter.green, filter.blue);
            }
            if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
                xRender::BlendKeyColor[bitsPixel](lpbDst, lpbSrc, x);
            else
            {
                if (bitsPixel == BITS_24)
                {
                    xRender::BlendKeyColorStretch[bitsPixel](lpbDst, lpbSrc, x);
                }
                else
                {
                    if (dwFlag == DRAW_NORMAL)
                        xRender::BlendKeyColorStretch[bitsPixel](lpbDst, lpbSrc, x);
                    else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                        xRender::BlendSrcOverStretchBicubic[bitsPixel](lpbDst, lpbSrc);
                    else
                        xRender::BlendSrcOverStretchBilinear[bitsPixel](lpbDst, lpbSrc);
                }
            }
        }
        else
        {
            if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
                xRender::BlendSrc[bitsPixel](lpbDst, lpbSrc);
            else
            {
                if (dwFlag == DRAW_NORMAL)
                    xRender::BlendSrcStretch[bitsPixel](lpbDst, lpbSrc);
                else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                    xRender::BlendSrcStretchBicubic[bitsPixel](lpbDst, lpbSrc);
                else if (dwFlag == DRAW_SMOOTH_AREAAVERAGE)
                    xRender::BlendSrcStretchAreaAveraging[bitsPixel](lpbDst, lpbSrc);
                else
                    xRender::BlendSrcStretchBilinear[bitsPixel](lpbDst, lpbSrc);
                
            }
        }
        
        return TRUE;
    }

    BOOL InternalDrawBitmapCPUPart(PBITMAP lpbDst, PBITMAPEX lpbSrc, LPCSIZE lpszDst, LPCRECT lprcClipped, BLENDFILTER filter, DWORD dwFlag, BYTE alpha)
    {
        if (!lpbDst || !lpbSrc)
            return FALSE;

        BYTE bitsPixel = GetBitsPixelType(lpbSrc->bmBitsPixel);

        if ((lpbSrc->bmWidth == lpszDst->cx) && (lpbSrc->bmHeight == lpszDst->cy))
        {
            BITMAPEX bmpSrc = *lpbSrc;
            bmpSrc.bmHeight = lpbDst->bmHeight;
            bmpSrc.bmWidth = lpbDst->bmWidth;
            bmpSrc.bmBits = (LPBYTE)bmpSrc.bmBits + lprcClipped->left * (lpbSrc->bmBitsPixel >> 3) + lprcClipped->top * bmpSrc.bmWidthBytes;
            if (filter.filter == BLEND_MULTIPLY)
            {
                xRender::BlendMul[bitsPixel](lpbDst, &bmpSrc);
            }
		    else if (filter.filter == BLEND_DSTOVER)
		    {
			    xRender::BlendDstOverStretch[bitsPixel](lpbDst, &bmpSrc);
		    }
            else if (filter.filter == BLEND_ALPHA || alpha != 0xFF)
            {
                if (alpha == 0)
                {
                    return TRUE;
                }
                else if (alpha == 0xFF)
                {
                    xRender::BlendSrcOver[bitsPixel](lpbDst, &bmpSrc);
                }
                else
                {
                    xRender::BlendAlpha[bitsPixel](lpbDst, &bmpSrc, alpha);
                }
            }
            else if (filter.filter == BLEND_KEYCOLOR)
            {
                xARGB x;
                if (bitsPixel == BITS_24)
                {
                    x = xARGBfrom(0xFF, filter.red, filter.green, filter.blue);
                }
                else
                {
                    x = xARGBfrom(0x00, filter.red, filter.green, filter.blue);
                }
                xRender::BlendKeyColor[bitsPixel](lpbDst, &bmpSrc, x);
            }
            else
            {
                BlendSrc[bitsPixel](lpbDst, &bmpSrc);
            }       
            return TRUE;
        }

        if (filter.filter == BLEND_MULTIPLY)
        {
            xRender::BlendMulStretchClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
        }
		else if (filter.filter == BLEND_DSTOVER)
		{
			xRender::BlendDstOverStretchClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
		}
        else if (filter.filter == BLEND_ALPHA || alpha != 0xFF)
        {
            if (alpha == 0)
            {
                return TRUE;
            }
            else if (alpha == 0xFF)
            {
                if (dwFlag == DRAW_NORMAL)
                    xRender::BlendSrcOverStretchClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
                else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                    xRender::BlendSrcOverStretchBicubicClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
                else
                    xRender::BlendSrcOverStretchBilinearClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
            }
            else
            {
                if (dwFlag == DRAW_NORMAL)
                    xRender::BlendAlphaStretchClip[bitsPixel](lpbDst, lpbSrc, alpha, lpszDst, lprcClipped);
                else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                    xRender::BlendAlphaStretchBicubicClip[bitsPixel](lpbDst, lpbSrc, alpha, lpszDst, lprcClipped);
                else
                    xRender::BlendAlphaStretchBilinearClip[bitsPixel](lpbDst, lpbSrc, alpha, lpszDst, lprcClipped);
            }
        }
        else if (filter.filter == BLEND_KEYCOLOR)
        {
            xARGB x;
            if (bitsPixel == BITS_24)
            {
                x = xARGBfrom(0xFF, filter.red, filter.green, filter.blue);
            }
            else
            {
                x = xARGBfrom(0x00, filter.red, filter.green, filter.blue);
            }
            if (bitsPixel == BITS_24)
            {
                xRender::BlendKeyColorStretchClip[bitsPixel](lpbDst, lpbSrc, x, lpszDst, lprcClipped);
            }
            else
            {
                if (dwFlag == DRAW_NORMAL)
                    xRender::BlendKeyColorStretchClip[bitsPixel](lpbDst, lpbSrc, x, lpszDst, lprcClipped);
                else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                    xRender::BlendSrcOverStretchBicubicClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
                else
                    xRender::BlendSrcOverStretchBilinearClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
            }
            
        }
        else
        {
            if (dwFlag == DRAW_NORMAL)
                xRender::BlendSrcStretchClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
            else if (dwFlag == DRAW_SMOOTH_BICUBIC)
                xRender::BlendSrcStretchBicubicClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
            else if (dwFlag == DRAW_SMOOTH_AREAAVERAGE)
                xRender::BlendSrcStretchAreaAveragingClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
            else
                xRender::BlendSrcStretchBilinearClip[bitsPixel](lpbDst, lpbSrc, lpszDst, lprcClipped);
        }

        return TRUE;
    }

/*    BOOL InternalDrawBitmap(xBitmap::CxBitmapDevice * pCanvas, LPCRECT lprcDst, xBitmap::CxBitmap * pBitmap, LPCRECT lprcSrc, DWORD dwFlag, BYTE alpha)
    {
        BLENDFILTER filter;
        pBitmap->GetFilter(&filter);
        CRect rcClipTarget(0, 0, 0, 0);
        if (!xMath::InternalGetClipTargetRect(pCanvas, lprcDst, &rcClipTarget))
        {
            return TRUE;
        }

        CRect rcDst = (CRect)(*lprcDst);
        if (rcClipTarget != rcDst)
        {
            rcClipTarget.OffsetRect(-lprcDst->left, -lprcDst->top);
            return InternalLockDrawBitmapPart(pCanvas, lprcDst, &rcClipTarget, pBitmap, lprcSrc, filter, dwFlag, alpha);
        }
        else
        {
            return InternalLockDrawBitmap(pCanvas, lprcDst, pBitmap, lprcSrc, filter, dwFlag, alpha);
        }
    }

    BOOL InternalLockDrawBitmap(xBitmap::CxBitmapDevice * pCanvas, LPCRECT lprcDstClipped, xBitmap::CxBitmap * pBitmap, LPCRECT lprcSrcClipped, BLENDFILTER filter, DWORD dwFlag, BYTE alpha)
    {
        BITMAP bmpDst;
        BITMAPEX bmpSrc;

        if (pCanvas->Lock(&bmpDst, lprcDstClipped))
        {
            if (pBitmap->LockEx(&bmpSrc, lprcSrcClipped))
            {
                InternalDrawBitmapCPU(&bmpDst, &bmpSrc, filter, dwFlag, alpha);
                pBitmap->Unlock();
            }

            pCanvas->Unlock();
        }

        return TRUE;
    }

    BOOL InternalLockDrawBitmapPart(xBitmap::CxBitmapDevice * pCanvas, LPCRECT lprcDst, LPCRECT lprcDstClipped, xBitmap::CxBitmap * pBitmap, LPCRECT lprcSrc, BLENDFILTER filter, DWORD dwFlag, BYTE alpha)
    {
        BITMAP bmpDst;
        BITMAPEX bmpSrc;

        CRect rcDst(lprcDstClipped);
        rcDst += CPoint(lprcDst->left, lprcDst->top);
        if (pCanvas->Lock(&bmpDst, &rcDst))
        {
            if (pBitmap->LockEx(&bmpSrc, lprcSrc))
            {
                CRect rcDst = (CRect)(*lprcDst);
                InternalDrawBitmapCPUPart(&bmpDst, &bmpSrc, &rcDst.Size(), lprcDstClipped, filter, dwFlag, alpha);
                pBitmap->Unlock();
            }

            pCanvas->Unlock();
        }

        return TRUE;
    } 

    BOOL InternalGetBitmapPixel(xBitmap::CxBitmap * pBitmap, int x, int y, LPXARGB lpx)
    {
        BITMAPEX bmp;
        CRect rcSrc(x, y, x + 1, y + 1);

        if (pBitmap->LockEx(&bmp, &rcSrc))
        {
            switch (bmp.bmBitsPixel)
            {
            case 8:
                *lpx = LPXARGB(bmp.bmColors)[*(LPBYTE)bmp.bmBits];
                break;
            case 24:
                *lpx = xARGBfrom(0xFF, *((LPBYTE)bmp.bmBits+2), *((LPBYTE)bmp.bmBits+1), *((LPBYTE)bmp.bmBits+0));
                break;
            case 32:
                *lpx = *((LPXARGB)bmp.bmBits);
                break;
            }
            pBitmap->Unlock();

            return TRUE;
        }

        return FALSE;
    }*/
}


/*
namespace xRender
{
  XG32_API void Myfunc(int a, int b)
  {
    return;
  }

  XG32_API BOOL InternalDrawBitmapCPU1(PBITMAP lpbDst, PBITMAP lpbSrc, BLENDFILTER filter, DWORD dwFlag, BYTE alpha)
  {
    if (!lpbDst || !lpbSrc)
      return FALSE;

    BYTE bitsPixel = xRender::GetBitsPixelType(lpbSrc->bmBitsPixel);

    if (filter.filter == BLEND_MULTIPLY)
    {
//       if ((lpbSrc->bmWidth == lpbDst->bmWidth) && (lpbSrc->bmHeight == lpbDst->bmHeight))
//         xRender::BlendMul[bitsPixel](lpbDst, lpbSrc);
//       else
//         xRender::BlendMulStretch[bitsPixel](lpbDst, lpbSrc);
    }

    xRender::InternalGetBitmapPixel(NULL, 0, 0,NULL);
    return TRUE;
    return xRender::InternalDrawBitmapCPU(lpbDst, (PBITMAPEX)(lpbSrc), filter, dwFlag, alpha);


    xRender::InternalLockDrawBitmap(NULL, NULL, NULL, NULL, filter, dwFlag, alpha);

    //xRender::InternalDrawBitmapCPUPart(NULL, (PBITMAP)(NULL), NULL, NULL, filter, dwFlag, alpha);
  }
}  */